package com.atldy.commerce.config;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;

import java.util.List;

/**
 * @version 1.0
 * @Author: lidongyang
 * @CreateTime: 2021-08-05 22:13
 * @Description： 事件推送  Aware  动态更新路由网关  进行监听
 */
@Slf4j
@Service
public class DynamicRouteServiceImpl implements ApplicationEventPublisherAware {

    /**
     * 写路由定义
     */
    private final RouteDefinitionWriter routeDefinitionWriter;

    /**
     * 获取现在使用的路由定义
     */
    private final RouteDefinitionLocator routeDefinitionLocator;

    /**
     * 事件推送
     */
    private ApplicationEventPublisher applicationEventPublisher;

    /**
     * 赋值
     */
    public DynamicRouteServiceImpl(RouteDefinitionWriter routeDefinitionWriter
            , RouteDefinitionLocator routeDefinitionLocator) {
        this.routeDefinitionWriter = routeDefinitionWriter;
        this.routeDefinitionLocator = routeDefinitionLocator;
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        //完成事件推送的初始化
        this.applicationEventPublisher = applicationEventPublisher;
    }

    /**
     * @author: 唐多令
     * @date: 2021/8/5 22:20
     * @param: [routeDefinition]
     * @description: 新增路由
     */
    public String addRouteDefinition(RouteDefinition routeDefinition) {
        log.info("load gateway add start route [{}]" + JSON.toJSONString(routeDefinition));
        //保存路由配置并刷新
        routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
        //发布时间通知给 gateway
        this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
        log.info("load gateway add end route [{}]" + JSON.toJSONString(routeDefinition));
        return " SAVE SUCCESS";
    }

    /**
     * @author: 唐多令
     * @date: 2021/8/5 22:59
     * @param: [routeDefinitions]
     * @description: 批量更新路由配置
     */
    public String updateRoutes(List<RouteDefinition> routeDefinitions) {
        log.info("load gateway batch update start route [{}]" + JSON.toJSONString(routeDefinitions));
        //获取本地网关都路由定义
        List<RouteDefinition> routeDefinitionList = routeDefinitionLocator.getRouteDefinitions().buffer().blockFirst();
        log.info("load local gateway route [{}]", JSONUtil.formatJsonStr(routeDefinitionList.toString()));
        //存在路由配置，根据路由id进行删除
        if (CollectionUtil.isNotEmpty(routeDefinitionList)) {
            routeDefinitionList.stream().forEach(routeDefinition -> {
                deleteRouteById(routeDefinition.getId());
            });
        }
        //批量更新
        routeDefinitions.stream().forEach(routeDefinition -> updateRouteDefinition(routeDefinition));
        //判断是否
        return "BATCH UPDATE SUCCESS ";
    }


    /**
     * 根据路由id删除路由配置
     */
    private String deleteRouteById(String routeId) {
        try {
            //删除路由配置并刷新
            routeDefinitionWriter.delete(Mono.just(routeId)).subscribe();
            this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
            return "DELETE SUCCESS";
        } catch (Exception e) {
            log.error("load gateway  delete route by id：[{}] ,error info:[{}]" + routeId, e.getMessage());
            return "DELETE FAIL";
        }
    }


    /**
     * 更新操作
     */
    private String updateRouteDefinition(RouteDefinition routeDefinition) {
        log.info("load gateway update start route [{}]" + JSON.toJSONString(routeDefinition));
        try {
            //删除路由配置并刷新
            routeDefinitionWriter.delete(Mono.just(routeDefinition.getId()));
        } catch (Exception e) {
            log.error("load gateway  update delete route by id：[{},{}]"  ,routeDefinition.getId(), e.getMessage());
            return "UPDATE DELETE FAIL";
        }
        try {
            //更新路由配置并刷新
            routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
            //发布时间通知给 gateway
            this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
            log.info("load gateway update end route [{}]" + JSON.toJSONString(routeDefinition));
            return "UPDATE SUCCESS";
        } catch (Exception e) {
            log.error("load gateway  update save route by id：[{}] ,error info:[{}]" + routeDefinition.getId(), e.getMessage());
            return "UPDATE SAVE FAIL";
        }

    }

}